/*
 * testing.c
 *
 *  Created on: 12/11/2011
 *      Author: utn_so
 */

#include "testing.h"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/statfs.h>
#include <string.h>
#include "socketMng.h"
#include "../../General/Serializable/serializable.h"
#include "structsFAT.h"
#include "socketMng.h"
#include "functionsFAT.h"
#include "cache.h"
#include "direccionamiento.h"

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <pthread.h>
#include <semaphore.h>

#define sizeOfCache 4096

int32_t ServerReady = 0;

void test_initialize()
{
	SocketMNG_setIP("127.0.0.1");
	SocketMNG_setPort(8000);
	SocketMNG_setMaxConnections(1);
}

void test_ClustersLibres()
{
	Fifo_CLUSTER listCluster;
	FIFO_CLUSTER_Create(&listCluster);
	getListOfFreeClusters(&listCluster, 0);
	Nodo_CLUSTER *nodo = listCluster.Head;
	int i;
	while (nodo != NULL)
	{
		printf("%d, ", nodo->cluster);
		((i % 100) == 0)?printf("\n"):0;
		i++;
		nodo = nodo->nxt;
	}
	FIFO_CLUSTER_Destroy(&listCluster);
}

void test_Direccionamiento()
{
	Fifo_CLUSTER listCluster;
	FIFO_SECTOR listSectors;

	FIFO_CLUSTER_Create(&listCluster);
	FIFO_SECTOR_Create(&listSectors);

	getListOfFreeClusters(&listCluster, 5);
	//mapClustersToSectors(listCluster, 8, &listSectors);

	Nodo_SECTOR *nodo = listSectors.Head;
	int i = 1;
	while (nodo != NULL) {
		printf("%d, ", nodo->sector);
		((i % 8) == 0)?printf("\n"):0;
		i++;
		nodo = nodo->nxt;
	}
	FIFO_SECTOR_Destroy(&listSectors);
	FIFO_CLUSTER_Destroy(&listCluster);
}

#define sizeOfCache 4096

void test_Cache(int MakeDump)
{
	const char * fileName1 = "/def.txt"; //clusters: 10
	const char * fileName2 = "/ghi.txt"; //clusters: 11,15
	const char * fileName3 = "/abc.txt"; //clusters: 18

	int i;
	char buffer[sizeOfCache];
	char outBuffer[sizeOfCache];

	Cache_AddFile(fileName1);
	Cache_AddFile(fileName2);
	Cache_AddFile(fileName3);

	for(i = 0; i < sizeOfCache - 1; i++) buffer[i] = '\0';
	buffer[i] = '\0';
	Cache_Write(fileName1, buffer, 10);

	for(i = 0; i < sizeOfCache - 1; i++) buffer[i] = 'b';
	buffer[i] = '\0';
	Cache_Write(fileName2, buffer, 11);

	for(i = 0; i < sizeOfCache - 1; i++) buffer[i] = 'B';
	buffer[i] = '\0';
	Cache_Write(fileName2, buffer, 15);

	for(i = 0; i < sizeOfCache - 1; i++) buffer[i] = 'C';
	buffer[i] = '\0';
	Cache_Write(fileName3, buffer, 18);

	Cache_AddFile(fileName1); //Se abre el mismo archivo fileName1

	Cache_Read(fileName1, outBuffer, 10);

	if (MakeDump)
		Cache_Dump();

	Cache_RemoveFile(fileName2);
	Cache_RemoveFile(fileName1);
	Cache_RemoveFile(fileName3);
	Cache_RemoveFile(fileName1);
}

void test_DumpCache()
{
	int i;
	setSizeOfCluster(4096);
	Cache_Initialize(4096);
	for(i = 0; i < 5; i++)
		test_Cache(1);
}

void test_Cache_aFile()
{
	const char * fileName1 = "/def.txt"; //clusters: 10

	int i;
	char buffer[sizeOfCache];
	char outBuffer[sizeOfCache];

	Cache_AddFile(fileName1);

	for(i = 0; i < sizeOfCache - 1; i++) buffer[i] = 'A';
	buffer[i] = '\0';
	Cache_Write(fileName1, buffer, 10);

	Cache_AddFile(fileName1); //Se abre el mismo archivo fileName1

	Cache_Read(fileName1, outBuffer, 10);

	if (memcmp(buffer, outBuffer, sizeOfCache) == 0)
		printf("OK\n");

	buffer[sizeOfCache - 2] = 'B';
	Cache_Write(fileName1, buffer, 10);
	if (memcmp(buffer, outBuffer, sizeOfCache) != 0)
		printf("OK\n");

	if (memcmp(buffer, outBuffer, sizeOfCache - 2) == 0 &&
	   (buffer[sizeOfCache - 2] == outBuffer[sizeOfCache - 2] + 1) &&
	   (buffer[sizeOfCache - 1] == outBuffer[sizeOfCache - 1]))
		printf("OK\n");

	Cache_Write(fileName1, buffer, 11); //Escritura de otro cluster

	Cache_RemoveFile(fileName1);
	Cache_RemoveFile(fileName1);
}

void test_Cache_aFile_2Clusters()
{
	const char * fileName1 = "/def.txt"; //clusters: 10

	int i;
	char buffer[sizeOfCache];
	char outBuffer[sizeOfCache];

	Cache_Initialize(2*4096);
	Cache_AddFile(fileName1);

	//Escribo 2 clusters
	for(i = 0; i < sizeOfCache - 1; i++) buffer[i] = 'A';
	buffer[i] = '\0';
	Cache_Write(fileName1, buffer, 10);

	for(i = 0; i < sizeOfCache - 1; i++) buffer[i] = 'B';
	buffer[i] = '\0';
	Cache_Write(fileName1, buffer, 11);

	//Leo 10,11,11
	Cache_Read(fileName1, outBuffer, 10);
	Cache_Read(fileName1, outBuffer, 11);
	Cache_Read(fileName1, outBuffer, 11);

	//Escribo 12 => se deberia reemplazar cluster 10
	buffer[sizeOfCache - 2] = 'B';
	Cache_Write(fileName1, buffer, 12);

	Cache_RemoveFile(fileName1);
}

void test_Serialize()
{
	Message aMsg, aMsg2, aMsg3;
	Serializable_t aSerializable;
	char buffer[1024];
	int32_t sizeBuffer = 1024;

	aMsg.type = msgRead;
	aMsg.sectorRequest = 19595;
	aMsg.contentSize = 0;
	aMsg.content = NULL;

	Serialize_Message(&aSerializable, aMsg);
	Deserialize_Message(&aMsg2, aSerializable);
	if (aMsg.type == aMsg2.type &&
		aMsg.sectorRequest == aMsg2.sectorRequest &&
		aMsg.contentSize == aMsg2.contentSize)
		printf("OK\n");
	Serializable_Free(&aSerializable);


	aMsg.type = msgWrite;
	aMsg.sectorRequest = 1221;
	aMsg.contentSize = sizeBuffer;
	aMsg.content = buffer;

	Serialize_Message(&aSerializable, aMsg);
	Deserialize_Message(&aMsg3, aSerializable);
	if (aMsg.type == aMsg3.type &&
		aMsg.sectorRequest == aMsg3.sectorRequest &&
		aMsg.contentSize == aMsg3.contentSize &&
		memcmp(aMsg.content, aMsg3.content, sizeBuffer) == 0)
		printf("OK\n");
	Serializable_Free(&aSerializable);
}

void CrearServerBobo()
{
	struct sockaddr_in sin;
	struct sockaddr_in pin;
	int sock_descr;
	int temp_sock_descr;
	int address_size;
	char buf[1024];
	int port = 8001;
	int i;

	sock_descr = socket(AF_INET, SOCK_STREAM, 0);
	if (sock_descr == -1)
		perror("socket");

	bzero(&sin, sizeof(sin));
	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr = INADDR_ANY;
	sin.sin_port = htons(port);

	if (bind(sock_descr, (struct sockaddr *)&sin, sizeof(sin)) == -1)
		perror("bind");

	if (listen(sock_descr, 20) == -1)
		perror("listen");

	printf("Esperando conexiones...");
	ServerReady = 1;

	while(1) {
		temp_sock_descr = accept(sock_descr, (struct sockaddr *)&pin, &address_size);
		if (temp_sock_descr == -1)
			perror("accept");
		if (recv(temp_sock_descr, buf, 512, 0) == -1)
			perror("recv");

		for(i = 0; i < 512; i++) buf[i] = 'A';
		printf("Peticion recibida, ahi te mando un sector\n");
		if (send(temp_sock_descr, buf, 512, 0) == -1)
			perror("send");

		close(temp_sock_descr);
	}
}

void test_Socket()
{
	char Ptr[512];
	int i;
	pthread_t server_thread;
	SocketMNG_setIP("127.0.0.1");
	SocketMNG_setPort(8001);
	SocketMNG_setMaxConnections(1);
	pthread_create(&server_thread, NULL, (void *) CrearServerBobo, NULL);
	while(!ServerReady); //Espera hasta que se acepten conexiones
	SocketMNG_readSector(5, Ptr);
	for (i = 0; i < 512; i++) Ptr[i] = 'A';
	SocketMNG_writeSector(5, Ptr, 512);
}

sem_t sem_test;

void func_sem_test(int i)
{
	sem_wait(&sem_test);
	while(1) {
		printf("Mi numero es %d\n", i);
		sleep(5);
	}
	sem_post(&sem_test);
}

void test_Semaphore()
{
	int i;
	pthread_t thr_sem_test[8];
	sem_init(&sem_test, 0, 5);
	for(i = 0; i < 8; i++)
		pthread_create(&thr_sem_test[i], NULL, (void *)func_sem_test, (void *)i);
	while(1){};
}

void test_PPDSend()
{
	int i;
	char letraMsg;
	char *data = calloc(512, 1);
	letraMsg = 'A';
	for(i = 0; i < 512; i++) data[i] = letraMsg;
	//1ro -> set parameters
	SocketMNG_setIP("127.0.0.1");
	SocketMNG_setPort(8000);
	SocketMNG_setMaxConnections(1);
	//2do -> Handshake
	//HandshakeToDisk();
	//3ro -> infinitas peticiones de escritura cambiando el contenido de los paquetes ( verificar que el ppd reciba todas )
	while (1) {
		SocketMNG_writeSector(1, data, 512);
		printf("Presionar una tecla para continuar");
		getchar();
		(letraMsg == 'Z') ? letraMsg = 'A' : letraMsg++;
		for(i = 0; i < 512; i++) data[i] = letraMsg;
	}
}

void test_PPDRecv()
{
	int i;
	char *data = calloc(512, 1);
	FILE * testPPDConn = fopen("testPPDConn.txt", "w+");

	//1ro -> set parameters
	SocketMNG_setIP("127.0.0.1");
	SocketMNG_setPort(8000);
	SocketMNG_setMaxConnections(1);
	//2do -> Handshake
	//HandshakeToDisk();
	//3ro -> pido la lectura de un sector
	while (1) {
		SocketMNG_readSector(1, data);
		data[511] = '\0';
		fwrite(data, 1, 512, testPPDConn);
		fflush(testPPDConn);
		printf("paquete leido\n");
		getchar();
	}
	free(data);
}

void test_FAT()
{
	loadFileAllocationTable();
}

void test_BootSector()
{
	char s[5];
	extern BootSector BootSectorInformation;
	test_initialize();
	setInfoBootSector();
	setFileAllocationTable();
	if (BootSectorInformation.bytes_per_sector == 512 &&
		BootSectorInformation.sectors_per_cluster == 8 &&
		BootSectorInformation.number_of_FATs      == 2 )
		printf("OK\n");
	scanf("%s", s);
}


